#!/usr/bin/env python
"""

Copyright 2009-2010-2011 Jordi Inglada.
jordi dot inglada at gmail dot com
"""

import string
import unittest

class MusicalMode:
    """
    Defines a musical mode
    | Mode 	    |Tonic relative  |        White| Interval        |
    |           |to major scale  |	note       | sequence        |
    |-----------|----------------| ------------|-----------------|
    | Ionian 	| I 	         |      C      | T-T-s-T-T-T-s   |
    | Dorian 	| II 	         |	    D      |T-s-T-T-T-s-T    |
    | Phrygian 	| III 	         |	    E      |s-T-T-T-s-T-T    |
    | Lydian 	| IV 	         |	    F      |T-T-T-s-T-T-s    |
    | Mixolydian| 	V 	         |	    G      |T-T-s-T-T-s-T    | 
    | Aeolian 	| VI	         | 	    A      |T-s-T-T-s-T-T    |
    | Locrian 	|VII 	         |	    B      |s-T-T-s-T-T-T    |
    """
    def __init__(self):
        """
        __init__(self)
        Initialize a new instance.
        """
        self.Tonic = 1
        self.Note = 'C'
        self.Sequence =  string.split("T-T-s-T-T-T-s",'-')
        return

class Chord:
    """
    Defines a chord
    """
    def __init__(self):
        """
        __init__(self)
        Initialize a new instance.
        """
        self.Mode = MusicalMode()
        self.Order = 3
        return

class RythmPattern:
    """
    Defines a rythm pattern
    """
    def __init__(self):
        """
        __init__(self)
        Initialize a new instance.
        """
        self.Times = 4
        self.TimesOver = 4
        self.Accents = (1)
        return

class RythmSequence:
    """
    A sequence of rythm patterns
    """
    def __init__(self):
        """
        __init__(self)
        Initialize a new instance.
        """
        self.Sequence = []
        self.Sequence.add(RythmPattern())
        return




class Style:
    """
    Defines a musical style
    """
    def __init__(self):
        """
        __init__(self)
        Initialize a new instance.
        """
        return


class PianoRollNote:
    """
    A note of a piano roll. Pitch is given by integer numbers (half a tone each)
    with respect to de middle c. For example Pitch=1 is c#, and Pitch=4 is e. 
    OnSetTime and OffSetTime are given in milliseconds.
    """
    def __init__(self):
        """
        __init__(self)
        Initialize a new instance.
        """
        self.Pitch = 0
        self.OnSetTime = 0
        self.OffSetTime = 1
        return


class PianoRoll:
    """
    A piano roll representation of a musical score. It is a list of notes.
    """
    def __init__(self):
        """
        __init__(self)
        Initialize a new instance.
        """
        self.Roll = []
        return
    def SetNote( self, theNote ):
        """
        Add a note to the roll
        """
        self.Roll.append( theNote )
        return

class Score:
    """
    The score representation using Lilypond notation
    """
    def __init__(self):
        """
        __init__(self)
        Initialize a new instance.
        """
        self.Relative = 'c'
        self.TimeSignature = (3,4)
        self.Clef = 'bass'
        self.Key = 'd-minor'
        #each voice will be a list of notes.
        #see http://lilypond.org/doc/v2.12/Documentation/user/lilypond-learning-big-page\#Voices-contain-music
        self.Voices = {}
        self.ScoreAsString = ""#will contain the ascii representation of the
            #score
        return

class ScoreToPianoRoll:
    """
    Generates a piano roll from a score
    """
    def __init__(self):
        return

class PianoRollToScore:
    """
    Generates a score from a piano roll. Needs to estimate many things from the
    piano roll before generating the score. Will use the methods described in
    'The cognition of basic musical structures' by David Temperley       
    """
    def __init__(self):
        self.TheScore = Score()
        return

    def GenerateScore(self, pianoRoll):
        self.EstimateRelative()
        self.EstimateTimeSignature()
        self.EstimateClef()
        self.EstimateKey()
        self.ExtractVoices()
        self.GengerateScoreAsString()

    def EstimateRelative(self):
        pass
    def EstimateTimeSignature(self):
        pass
    def EstimateClef(self):
        pass
    def EstimateKey(self):
        pass
    def ExtractVoices(self):
        pass    
    def GengerateScoreAsString(self):
        pass

class TestArsenicGourmet(unittest.TestCase):

    def setUp(self):
        #self.seq = range(10)
        pass

    def test_pianoRoll(self):
        pr = PianoRoll()
        aNote = PianoRollNote()
        aNote.Pitch = 440
        aNote.OnSetTime = 1
        aNote.OffSetTime = 2
        pr.SetNote( aNote )

        





def main():
    """
    main()
    Module mainline (for standalone execution)
    """

    return


if __name__ == "__main__":
    unittest.main()
